package se.kayarr.cardplay.gameplay;

import lombok.Getter;
import se.kayarr.cardplay.exceptions.FieldPositionOccupiedException;
import se.kayarr.cardplay.exceptions.PositionOutsideFieldException;


public class Field {
	@Getter private Session session;
	@Getter private Player owner;
	@Getter private int width;
	@Getter private int height;
	
	private UnitCard.Instance[] field;
	
	public Field(Player owner, int width, int height) {
		this.session = owner.getSession();
		this.owner = owner;
		this.width = width;
		this.height = height;
		
		this.field = new UnitCard.Instance[width*height];
	}
	
	public String outputField() {
		StringBuilder builder = new StringBuilder();
		for(int y = 0; y < height; y++) {
			builder.append(outputRow(y)).append(System.getProperty("line.separator"));
		}
		return builder.toString();
	}
	
	public String outputRow(int y) {
		StringBuilder builder = new StringBuilder();
		for(int x = 0; x < width; x++) {
			builder.append(outputTile(x, y));
		}
		return builder.toString();
	}
	
	public String outputTile(int x, int y) {
		UnitCard.Instance fieldTile = field[y*width + x];
		return new StringBuilder().append('[')
				.append(fieldTile != null ? fieldTile.getCard().getDisplayId() : "____")
				.append(']').toString();
	}
	
	public boolean canPlaceUnitCard(int x, int y, UnitCard.Instance instance) throws PositionOutsideFieldException {
		return instance.canPlaceAt(this, x, y);
	}
	
	public void putUnitCard(int x, int y, UnitCard.Instance instance)
			throws FieldPositionOccupiedException, PositionOutsideFieldException {
		if(!canPlaceUnitCard(x, y, instance))
			throw new FieldPositionOccupiedException();
		
		field[y*width + x] = instance;
		instance.x = x;
		instance.y = y;
		instance.onPlaced();
	}
	
	public UnitCard.Instance getUnitCard(int x, int y) throws PositionOutsideFieldException {
		int i = y*width + x;
		if(i < 0 || i >= field.length) throw new PositionOutsideFieldException(x, y);
		
		return field[i];
	}
	
	public int unitsOnField() {
		int counter = 0;
		for(UnitCard.Instance instance : field) {
			if(instance != null) counter++;
		}
		return counter;
	}
	
	public UnitCard.Instance findUnitById(String id) {
		for(UnitCard.Instance instance : field) {
			if(instance != null && instance.getCard().getDisplayId().equalsIgnoreCase(id)) return instance;
		}
		
		return null;
	}
	
	public UnitCard.Instance findUnitByRefId(String refId) {
		for(UnitCard.Instance instance : field) {
			if(instance != null && instance.getCard().getRefId().equals(refId)) return instance;
		}
		
		return null;
	}
	
	public UnitCard.Instance findUnitByCard(Card card) {
		for(UnitCard.Instance instance : field) {
			if(instance != null && instance.getCard().getClass() == card.getClass()) return instance;
		}
		
		return null;
	}
	
	void cleanupDeadUnits() {
		for(int i = 0; i < field.length; i++) {
			if(field[i] != null && field[i].getHealth().isAtMin()) {
				session.narrate(field[i] + " has been killed..."); //TODO Colors perhaps?
				field[i] = null; //TODO Move card to discard pile (if there are even going to be discard piles)
			}
		}
	}
}
